
#include <cstdio>

#include <promote/String.hpp>
#include <promote/Timestamp.hpp>

#include "BinomialTree.hpp"
#include "BlackScholes.hpp"
#include "ExpiryCalculator.hpp"
#include "VanillaOption.hpp"

using namespace provident;

int main(void)
{
    BinomialTree<CoxRossRubinstein> crr;
    BinomialTree<CoxRossRubinstein>::Evaluation crrEval;
    BinomialTree<EqualProbabilities> ep;
    BinomialTree<EqualProbabilities>::Evaluation epEval;
    BinomialTree<JarrowRudd> jr;
    BinomialTree<JarrowRudd>::Evaluation jrEval;
    BinomialTree<Tian> tian;
    BinomialTree<Tian>::Evaluation tianEval;
    BinomialTree<Trigeorgis> trig;
    BinomialTree<Trigeorgis>::Evaluation trigEval;
    BlackScholes bs;
    double bsPrice;
    double rate = 0.1;
    int steps = 200;

    promote::Timestamp maturity;
    maturity.date(6,19,2011);
    printf("Maturity = %d/%d/%d\n", maturity.month(), maturity.dayOfMonth(), maturity.year());
    ExpiryCalculator expiryCalc(ExpiryCalculator::CALENDAR_YEAR, 6, 8, 2011);
    printf("YearsTilExpiry = %f\n", expiryCalc.yearsTilExpiry(maturity));

    // American Call
    printf("American Call....\n");
    VanillaOption optionAC(promote::String("AAPL OPTION NAME",false),
                           promote::String("AAPL",false),
                           expiryCalc.yearsTilExpiry(maturity),
                           260, VanillaOption::CALL,
                           VanillaOption::AMERICAN);
    crr.valuate(crrEval, optionAC, 261.835, 0.45488, rate, steps);
    printf("Cox/Ross/Rubinstein price = %f\n", crrEval.theoreticalPrice());
    ep.valuate(epEval, optionAC, 261.835, 0.45488, rate, steps);
    printf("Equal Probabilities price = %f\n", epEval.theoreticalPrice());
    jr.valuate(jrEval, optionAC, 261.835, 0.45488, rate, steps);
    printf("Jarrow-Rudd         price = %f\n", jrEval.theoreticalPrice());
    tian.valuate(tianEval, optionAC, 261.835, 0.45488, rate, steps);
    printf("Tian                price = %f\n", tianEval.theoreticalPrice());
    trig.valuate(trigEval, optionAC, 261.835, 0.45488, rate, steps);
    printf("Trigeorgis          price = %f\n", trigEval.theoreticalPrice());
    bsPrice = bs.valuate(optionAC, 261.835, 0.45488, rate);
    printf("Black Scholes       price = %f\n", bsPrice);
    
    // European Call
    printf("\nEuropean Call....\n");
    VanillaOption optionEC(promote::String("AAPL OPTION NAME",false),
                           promote::String("AAPL",false),
                           expiryCalc.yearsTilExpiry(maturity),
                           260, VanillaOption::CALL,
                           VanillaOption::EUROPEAN);
    crr.valuate(crrEval, optionEC, 261.835, 0.45488, rate, steps);
    printf("Cox/Ross/Rubinstein price = %f\n", crrEval.theoreticalPrice());
    ep.valuate(epEval, optionEC, 261.835, 0.45488, rate, steps);
    printf("Equal Probabilities price = %f\n", epEval.theoreticalPrice());
    jr.valuate(jrEval, optionEC, 261.835, 0.45488, rate, steps);
    printf("Jarrow-Rudd         price = %f\n", jrEval.theoreticalPrice());
    tian.valuate(tianEval, optionEC, 261.835, 0.45488, rate, steps);
    printf("Tian                price = %f\n", tianEval.theoreticalPrice());
    trig.valuate(trigEval, optionEC, 261.835, 0.45488, rate, steps);
    printf("Trigeorgis          price = %f\n", trigEval.theoreticalPrice());
    bsPrice = bs.valuate(optionEC, 261.835, 0.45488, rate);
    printf("Black Scholes       price = %f\n", bsPrice);
    
    // American Put
    printf("\nAmerican Put....\n");
    VanillaOption optionAP(promote::String("AAPL OPTION NAME",false),
                           promote::String("AAPL",false),
                           expiryCalc.yearsTilExpiry(maturity),
                           260, VanillaOption::PUT,
                           VanillaOption::AMERICAN);
    crr.valuate(crrEval, optionAP, 261.835, 0.45488, rate, steps);
    printf("Cox/Ross/Rubinstein price = %f\n", crrEval.theoreticalPrice());
    ep.valuate(epEval, optionAP, 261.835, 0.45488, rate, steps);
    printf("Equal Probabilities price = %f\n", epEval.theoreticalPrice());
    jr.valuate(jrEval, optionAP, 261.835, 0.45488, rate, steps);
    printf("Jarrow-Rudd         price = %f\n", jrEval.theoreticalPrice());
    tian.valuate(tianEval, optionAP, 261.835, 0.45488, rate, steps);
    printf("Tian                price = %f\n", tianEval.theoreticalPrice());
    trig.valuate(trigEval, optionAP, 261.835, 0.45488, rate, steps);
    printf("Trigeorgis          price = %f\n", trigEval.theoreticalPrice());
    bsPrice = bs.valuate(optionAP, 261.835, 0.45488, rate);
    printf("Black Scholes       price = %f\n", bsPrice);

    // European Put
    printf("\nEuropean Put....\n");
    VanillaOption optionEP(promote::String("AAPL OPTION NAME",false),
                           promote::String("AAPL",false),
                           expiryCalc.yearsTilExpiry(maturity),
                           260, VanillaOption::PUT,
                           VanillaOption::EUROPEAN);
    crr.valuate(crrEval, optionEP, 261.835, 0.45488, rate, steps);
    printf("Cox/Ross/Rubinstein price = %f\n", crrEval.theoreticalPrice());
    ep.valuate(epEval, optionEP, 261.835, 0.45488, rate, steps);
    printf("Equal Probabilities price = %f\n", epEval.theoreticalPrice());
    jr.valuate(jrEval, optionEP, 261.835, 0.45488, rate, steps);
    printf("Jarrow-Rudd         price = %f\n", jrEval.theoreticalPrice());
    tian.valuate(tianEval, optionEP, 261.835, 0.45488, rate, steps);
    printf("Tian                price = %f\n", tianEval.theoreticalPrice());
    trig.valuate(trigEval, optionEP, 261.835, 0.45488, rate, steps);
    printf("Trigeorgis          price = %f\n", trigEval.theoreticalPrice());
    bsPrice = bs.valuate(optionEP, 261.835, 0.45488, rate);
    printf("Black Scholes       price = %f\n", bsPrice);

    return 0;
}

